package heap

import (
	"fmt"
	"jvmgo/classfile"
)

type Constant interface {
}

type ConstantPool struct {
	class     *Class
	constants []Constant
}

func (self *ConstantPool) GetConstant(index uint) Constant {
	if c := self.constants[index]; c != nil {
		return c
	}
	panic(fmt.Sprintf("No Constants at Index %d", index))
}

// 将class内的常量池转换为运行时常量池
func newConstantPool(class *Class, cfCp classfile.ConstantPool) *ConstantPool {
	cpCount := len(cfCp)
	consts := make([]Constant, cpCount)
	rtCp := &ConstantPool{class: class, constants: consts}

	for i := 0; i < cpCount; i++ {
		cpInfo := cfCp[i]
		switch cpInfo.(type) {
		case *classfile.ConstantIntegerInfo:
			consts[i] = cpInfo.(*classfile.ConstantIntegerInfo).Value()
		case *classfile.ConstantFloatInfo:
			consts[i] = cpInfo.(*classfile.ConstantFloatInfo).Value()
		case *classfile.ConstantLongInfo:
			consts[i] = cpInfo.(*classfile.ConstantLongInfo).Value()
			i++
		case *classfile.ConstantDoubleInfo:
			consts[i] = cpInfo.(*classfile.ConstantDoubleInfo).Value()
			i++
		case *classfile.ConstantStringInfo:
			consts[i] = cpInfo.(*classfile.ConstantStringInfo)
		case *classfile.ConstantClassInfo:
			consts[i] = newClassRef(rtCp, cpInfo.(*classfile.ConstantClassInfo))
		case *classfile.ConstantFieldrefInfo:
			fieldRefInfo := cpInfo.(*classfile.ConstantFieldrefInfo)
			consts[i] = newFieldRef(rtCp, fieldRefInfo)
		case *classfile.ConstantMethodrefInfo:
			methodRef := cpInfo.(*classfile.ConstantMethodrefInfo)
			consts[i] = newMethodRef(rtCp, methodRef)
		case *classfile.ConstantInterfaceMethodrefInfo:
			interfaceMethodRef := cpInfo.(*classfile.ConstantInterfaceMethodrefInfo)
			consts[i] = newInterfaceMethodRef(rtCp, interfaceMethodRef)
		case *classfile.ConstantUtf8Info:
			consts[i] = cpInfo.(*classfile.ConstantUtf8Info)
		}
	}
	return rtCp
}
